open Castling;;
open C_lexical;;

module Syntax (Integer: NumericType) (Real: NumericType) (WideString: StringType)
	(LexicalElement: LexicalElementType with type integer = Integer.t and type real = Real.t and type wide_string = WideString.t) =
struct
	open LexicalElement;;
	module CPG = ParserGenerator (LexicalElement);;
	open CPG;;
	
	let any_identifier = element (I "");;
	
	let rec translation_unit = lazy !! (
		one_of ~name:"decls" [
			"next_decl", position_with external_declaration >> translation_unit;
			"end_of_decls", epsilon]
	) and external_declaration = lazy !! (
		one_of ~name:"declaration" [
			"pragma", preorocessor_directive;
			"include_begin", element (Include_begin "");
			"include_end", skip (element Include_end);
			"function", function_definition;
			"forward", forward_definition;
			"interface", interface_definition;
			"implementation", implementation_definition;
			"protocol", protocol_definition;
			"declaration", declaration]
	) and function_definition = lazy !! (
		declaration_specifiers >> declarator >>
		(* K&R-style-args_declaration_list_opt >> *)
		compound_statement
	) and forward_definition = lazy !! (
		skip (element (ObjC_directive Reserved.CLASS)) >> classname_list >> skip (element Semicolon)
	) and classname_list = lazy !! (
		one_of ~name:"classnames" [
			"next_classname", any_identifier >> skip (element Comma) >> classname_list;
			"end_of_classnames", any_identifier]
	) and interface_definition = lazy !! (
		skip (element (ObjC_directive Reserved.INTERFACE)) >> any_identifier >> superclass >>
		skip (element L_curly) >> member_declaration_list_opt >> skip (element R_curly) >>
		method_list_opt >>
		skip (element (ObjC_directive Reserved.END))
	) and implementation_definition = lazy !! (
		skip (element (ObjC_directive Reserved.IMPLEMENTATION)) >> any_identifier >>
		method_list_opt >>
		skip (element (ObjC_directive Reserved.END))
	) and protocol_definition = lazy !! (
		skip (element (ObjC_directive Reserved.PROTOCOL)) >> any_identifier >>
		method_list_opt >>
		skip (element (ObjC_directive Reserved.END))
	) and superclass = lazy !! (
		one_of ~name:"superclass" [
			"inheritance", skip (element (Colon)) >> any_identifier;
			"inheritance_protocols", skip (element (Colon)) >> any_identifier >>
				skip (element (LT)) >> classname_list >> skip (element (GT));
			"no_superclass", epsilon]
	) and method_list_opt = lazy !! (
		one_of ~name:"methods" [
			"next_method", method_definition >> method_list_opt;
			"end_of_methods", epsilon]
	) and method_definition = lazy !! (
		one_of_elements [Plus; Minus] >>
		cast_opt >>
		method_prototype >>
		one_of ~name:"method_body" [
			"body", compound_statement;
			"no_body", skip (element Semicolon)]
	) and cast_opt = lazy !! (
		one_of ~name:"typecast" [
			"no_type", epsilon;
			"has_type", skip (element L_paren) >> parameter_declaration >> skip (element R_paren)]
	) and method_prototype = lazy !! (
		one_of ~name:"method_prototype" [
			"", method_with_args;
			"no_arg_method", any_identifier]
	) and method_with_args = lazy !! (
		one_of ~name:"method_prototype" [
			"next_method_prototype", single_selector >> method_with_args;
			"end_perform_method", skip (element Colon) >> cast_opt >> any_identifier;
			"end_varargs_method", skip (element Comma) >> skip (element Varargs);
			"end_method_prototype", single_selector]
	) and single_selector = lazy !! (
		any_identifier >> skip (element Colon) >> cast_opt >> any_identifier
	) and member_declaration_list_opt = lazy !! (
		one_of ~name:"decls" [
			"next_decl", position_with member_declaration >> member_declaration_list_opt;
			"end_of_decls", epsilon]
	) and member_declaration = lazy !! (
		one_of ~name:"declaration" [
			"pragma", preorocessor_directive;
			"private", skip (element (ObjC_directive Reserved.PRIVATE));
			"declaration", declaration]
	) and declaration = lazy !! (
		declaration_specifiers >> init_declarator_list_opt >> skip (element Semicolon)
	) and declaration_specifiers = lazy !! (
		one_of ~name:"declaration_specifiers" [
			"typename_spec", any_identifier >> protocol_qualifier_opt >> typed_declaration_specifiers_opt;
			"extension_spec", skip (element Extension) >> declaration_specifiers;
			"storage_class_spec", storage_class_specifier >> declaration_specifiers;
			"type_spec", type_specifier >> typed_declaration_specifiers_opt;
			"type_qualifier_spec", type_qualifier >> declaration_specifiers;
			"function_spec", function_specifier >> declaration_specifiers]
	) and typed_declaration_specifiers_opt = lazy !! (
		one_of ~name:"declaration_specifiers" [
			"no_declspec", epsilon;
			"", typed_declaration_specifiers]
	) and typed_declaration_specifiers = lazy !! (
		one_of ~name:"declaration_specifiers" [
			"storage_class_spec", storage_class_specifier >> typed_declaration_specifiers_opt;
			"type_spec", type_specifier >> typed_declaration_specifiers_opt;
			"type_qualifier_spec", type_qualifier >> typed_declaration_specifiers_opt;
			"function_spec", function_specifier >> typed_declaration_specifiers_opt]
	) and storage_class_specifier = lazy !! (
		one_of_elements [
			R Reserved.TYPEDEF;
			R Reserved.EXTERN;
			R Reserved.STATIC;
			R Reserved.AUTO;
			R Reserved.REGISTER]
	) and type_specifier = lazy !! (
		one_of ~name:"type_specifier" [
			"void", skip (element (R Reserved.VOID));
			"basic_type", basic_type;
			"", struct_or_union_specifier;
			"", enum_specifier]
	) and basic_type = lazy !! (
		one_of_elements [
			R Reserved.CHAR;
			R Reserved.SHORT;
			R Reserved.INT;
			R Reserved.LONG;
			R Reserved.FLOAT;
			R Reserved.DOUBLE;
			R Reserved.SIGNED;
			R Reserved.UNSIGNED;
			R Reserved.BOOL;
			R Reserved.IMAGINARY;
			R Reserved.COMPLEX;
			R Reserved.WCHAR_T;
			Int64]
	) and type_qualifier = lazy !! (
		one_of_elements [
			Attribute "";
			R Reserved.CONST;
			R Reserved.RESTRICT;
			R Reserved.VOLATILE]
	) and function_specifier = lazy !! (
		element (R Reserved.INLINE)
	) and struct_or_union = lazy !! (
		one_of_elements [R Reserved.STRUCT; R Reserved.UNION]
	) and struct_or_union_specifier = lazy !! (
		one_of ~name:"type_specifier" [
			"struct_or_union_ref", struct_or_union >> any_identifier;
			"struct_or_union", struct_or_union >> any_identifier >>
				skip (element L_curly) >> member_declaration_list_opt >> skip (element R_curly);
			"struct_or_union_notag", struct_or_union >>
				skip (element L_curly) >> member_declaration_list_opt >> skip (element R_curly)]
	) and enum_specifier = lazy !! (
		one_of ~name:"type_specifier" [
			"enum_ref", skip (element (R Reserved.ENUM)) >> any_identifier;
			"enum", skip (element (R Reserved.ENUM)) >> any_identifier >>
				skip (element L_curly) >> enums >> skip (element R_curly);
			"enum_notag", skip (element (R Reserved.ENUM)) >>
				skip (element L_curly) >> enums >> skip (element R_curly)]
	) and enums = lazy !! (
		one_of ~name:"enums" [
			"next_enum", enum_item >> skip (element Comma) >> enums;
			"end_of_enums", enum_item;
			"no_enum", epsilon]
	) and enum_item = lazy !! (
		one_of ~name:"enum_item" [
			"represented_item", any_identifier >> skip (element Assign) >> assignment;
			"item", any_identifier]
	) and protocol_qualifier_opt = lazy !! (
		one_of ~name:"protocol_qualifier" [
			"protocol_ref", skip (element LT) >> any_identifier >> skip (element GT);
			"no_protocol", epsilon]
	) and attribute_opt = lazy !! (
		one_of ~name:"attribute" [
			"has_attribute", element (Attribute "");
			"no_attribute", epsilon]
	) and init_declarator_list_opt = lazy !! (
		one_of ~name:"init_declarators" [
			"", init_declarator_list;
			"no_init_decl", epsilon]
	) and init_declarator_list = lazy !! (
		one_of ~name:"init_declarators" [
			"next_init_decl", init_declarator >> skip (element Comma) >> init_declarator_list;
			"end_of_init_decls", init_declarator]
	) and init_declarator_list2 = lazy !! (
		one_of ~name:"init_declarators" [
			"next_init_decl", init_declarator2 >> skip (element Comma) >> init_declarator_list;
			"end_of_init_decls", init_declarator2]
	) and init_declarator = lazy !! (
		one_of ~name:"init_declarator" [
			"simple_declarator", declarator;
			"initialized_declarator", declarator >> skip (element Assign) >> initializer_expr;
			"represented_declarator", declarator >> skip (element Colon) >> element (Int_literal (Signed_int, Integer.zero))]
	) and init_declarator2 = lazy !! (
		one_of ~name:"init_declarator" [
			"simple_declarator", declarator2;
			"initialized_declarator", declarator2 >> skip (element Assign) >> initializer_expr]
	) and declarator = lazy !! (
		one_of ~name:"declarator" [
			"pointer", skip (element Asterisk) >> declarator_with_type_qualifier;
			"", direct_declarator]
	) and declarator2 = lazy !! (
		one_of ~name:"declarator" [
			"pointer", skip (element Asterisk) >> declarator_with_type_qualifier;
			"", direct_declarator2]
	) and declarator_with_type_qualifier = lazy !! (
		one_of ~name:"declarator" [
			"with_type_qualifier", type_qualifier >> declarator_with_type_qualifier;
			"", declarator]
	) and direct_declarator = lazy !! (
		one_of ~name:"declarator" [
			"name", any_identifier;
			"paren", skip (element L_paren) >> attribute_opt >> declarator >> skip (element R_paren);
			"array", direct_declarator >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"unconstrained_array", direct_declarator >> skip (element L_bracket) >> skip (element R_bracket);
			"parameters", direct_declarator >> skip (element L_paren) >> parameter_list_opt >> skip (element R_paren) >> attribute_opt]
	) and direct_declarator2 = lazy !! (
		one_of ~name:"declarator" [
			"name", any_identifier;
			"array", direct_declarator2 >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"unconstrained_array", direct_declarator2 >> skip (element L_bracket) >> skip (element R_bracket);
			"parameters", direct_declarator2 >> skip (element L_paren) >> parameter_list_opt >> skip (element R_paren) >> attribute_opt]
	) and abstract_declarator = lazy !! (
		one_of ~name:"declarator" [
			"no_name", epsilon;
			"pointer", skip (element Asterisk) >> abstract_declarator_with_type_qualifier;
			"", abstract_direct_declarator]
	) and abstract_declarator_with_type_qualifier = lazy !! (
		one_of ~name:"declarator" [
			"with_type_qualifier", type_qualifier >> abstract_declarator_with_type_qualifier;
			"", abstract_declarator]
	) and abstract_direct_declarator = lazy !! (
		one_of ~name:"declarator" [
			"name", any_identifier;
			"paren", skip (element L_paren) >> attribute_opt >> abstract_declarator >> skip (element R_paren);
			"array", abstract_direct_declarator >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"unconstrained_array", abstract_direct_declarator >> skip (element L_bracket) >> skip (element R_bracket);
			"parameters", abstract_direct_declarator >> skip (element L_paren) >> parameter_list_opt >> skip (element R_paren) >> attribute_opt]
	) and parameter_list_opt = lazy !! (
		one_of ~name:"parameters" [
			"no_param", epsilon;
			"", parameter_list]
	) and parameter_list = lazy !! (
		one_of ~name:"parameters" [
			"next_param", parameter_declaration >> skip (element Comma) >> parameter_list;
			"end_varargs", skip (element Varargs);
			"end_param", parameter_declaration]
	) and parameter_declaration = lazy !! (
		declaration_specifiers >> abstract_declarator
	) and compound_statement = lazy !! (
		skip (element L_curly) >> statement_list_opt >> skip (element R_curly)
	) and statement_list_opt = lazy !! (
		one_of ~name:"statements" [
			"next_statement", statement >> statement_list_opt;
			"end_of_statements", epsilon]
	) and argument_expression_list_opt = lazy !! (
		one_of ~name:"expression" [
			"no_expression", epsilon;
			"", expression_in_paren]
	) and expression_opt = lazy !! (
		one_of ~name:"expression" [
			"no_expression", epsilon;
			"", expression]
	) and primary = lazy !! (
		one_of ~name:"expression" [
			"literal", one_of_elements [
				Char_literal '\x00';
				Chars_literal "";
				Wchar_literal 0l;
				Wchars_literal WideString.empty;
				ObjC_string_literal "";
				Int_literal (Signed_int, Integer.zero);
				Float_literal (Float, Real.zero);
				Invalid_literal];
			"var", any_identifier]
	) and postfix = lazy !! (
		one_of ~name:"expression" [
			"", primary;
			"", skip (element L_paren) >> expression_in_paren >> skip (element R_paren);
			"cast", skip (element L_paren) >> expression_in_paren >> skip (element R_paren) >> unary_in_cast;
			"dot", postfix >> skip (element Period) >> any_identifier;
			"arrow", postfix >> skip (element Arrow) >> any_identifier;
			"post_incr", postfix >> skip (element Increment);
			"post_decr", postfix >> skip (element Decrement);
			"index", postfix >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"call", postfix >> skip (element L_paren) >> argument_expression_list_opt >> skip (element R_paren);
			"send", skip (element L_bracket) >> expression_in_messaging >> message >> skip (element R_bracket)]
	) and statement_postfix = lazy !! (
		one_of ~name:"expression" [
			"", skip (element L_paren) >> expression_in_paren >> skip (element R_paren);
			"dot", statement_postfix >> skip (element Period) >> any_identifier;
			"dot", primary >> skip (element Period) >> any_identifier;
			"arrow", statement_postfix >> skip (element Arrow) >> any_identifier;
			"arrow", primary >> skip (element Arrow) >> any_identifier;
			"post_incr", statement_postfix >> skip (element Increment);
			"post_incr", primary >> skip (element Increment);
			"post_decr", statement_postfix >> skip (element Decrement);
			"post_decr", primary >> skip (element Decrement);
			"index", statement_postfix >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"index", primary >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"call", statement_postfix >> skip (element L_paren) >> argument_expression_list_opt >> skip (element R_paren);
			"call", primary >> skip (element L_paren) >> argument_expression_list_opt >> skip (element R_paren);
			"send", skip (element L_bracket) >> expression_in_messaging >> message >> skip (element R_bracket)]
	) and messaging_postfix = lazy !! (
		one_of ~name:"expression" [
			"", primary;
			"", skip (element L_paren) >> expression_in_paren >> skip (element R_paren);
			"dot", messaging_postfix >> skip (element Period) >> any_identifier;
			"arrow", messaging_postfix >> skip (element Arrow) >> any_identifier;
			"post_incr", messaging_postfix >> skip (element Increment);
			"post_decr", messaging_postfix >> skip (element Decrement);
			"index", messaging_postfix >> skip (element L_bracket) >> expression >> skip (element R_bracket);
			"call", messaging_postfix >> skip (element L_paren) >> argument_expression_list_opt >> skip (element R_paren);
			"send", skip (element L_bracket) >> expression_in_messaging >> message >> skip (element R_bracket)]
	) and unary = lazy !! (
		one_of ~name:"expression" [
			"", postfix;
			"incr", skip (element Increment) >> unary;
			"decr", skip (element Decrement) >> unary;
			"unary", one_of_elements [
				Ampersand; Asterisk; Plus; Minus; Tilde; Exclamation;
				Extension; Real; Imag] >> unary;
			"sizeof", skip (element (R Reserved.SIZEOF)) >>
				skip (element L_paren) >> expression_in_paren >> skip (element R_paren)]
	) and unary_in_cast = lazy !! (
		one_of ~name:"expression" [
			"", primary;
			"unary", one_of_elements [Tilde; Exclamation] >> primary]
	) and statement_unary = lazy !! (
		one_of ~name:"expression" [
			"", statement_postfix;
			"incr", skip (element Increment) >> unary;
			"decr", skip (element Decrement) >> unary]
	) and multiplicative = lazy !! (
		one_of ~name:"expression" [
			"", unary;
			"multiplicative", multiplicative >> one_of_elements [Asterisk; Slash; Percent] >> unary]
	) and additive = lazy !! (
		one_of ~name:"expression" [
			"", multiplicative;
			"additive", additive >> one_of_elements [Plus; Minus] >> multiplicative]
	) and shift = lazy !! (
		one_of ~name:"expression" [
			"", additive;
			"shift", shift >> one_of_elements [L_shift; R_shift] >> additive]
	) and relational = lazy !! (
		one_of ~name:"expression" [
			"", shift;
			"relational", relational >> one_of_elements [GT; LT; GE; LE] >> shift]
	) and equality = lazy !! (
		one_of ~name:"expression" [
			"", relational;
			"equality", equality >> one_of_elements [EQ; NE] >> relational]
	) and and_expression = lazy !! (
		one_of ~name:"expression" [
			"", equality;
			"and", and_expression >> skip (element Ampersand) >> equality]
	) and xor_expression = lazy !! (
		one_of ~name:"expression" [
			"", and_expression;
			"xor", xor_expression >> skip (element Caret) >> and_expression]
	) and or_expression = lazy !! (
		one_of ~name:"expression" [
			"", xor_expression;
			"or", or_expression >> skip (element Vertical) >> xor_expression]
	) and logical_and = lazy !! (
		one_of ~name:"expression" [
			"", or_expression;
			"and_then", logical_and >> skip (element And) >> or_expression]
	) and logical_or = lazy !! (
		one_of ~name:"expression" [
			"", logical_and;
			"or_else", logical_or >> skip (element Or) >> logical_and]
	) and conditional = lazy !! (
		one_of ~name:"expression" [
			"", logical_or;
			"conditional", logical_or >> skip (element Question) >> expression >> skip (element Colon) >> conditional]
	) and assignment = lazy !! (
		one_of ~name:"expression" [
			"", conditional;
			"assignment", unary >> assignment_operator >> assignment]
	) and statement_expression = lazy !! (
		one_of ~name:"expression" [
			"", statement_unary;
			"assignment", primary >> assignment_operator >> assignment;
			"assignment", statement_unary >> assignment_operator >> assignment]
	) and expression = lazy !! (
		one_of ~name:"expression" [
			"", assignment;
			"sequence", assignment >> skip (element Comma) >> expression]
	) and expression_in_paren = lazy !! (
		one_of ~name:"expression" [
			"", expression;
			"type", typed_declaration_specifiers >> abstract_declarator]
	) and expression_in_messaging = lazy !! (
		messaging_postfix
	) and initializer_expr = lazy !! (
		one_of ~name:"expression" [
			"struct_initializer", skip (element L_curly) >> struct_items >> skip (element R_curly);
			"", assignment]
	) and struct_items = lazy !! (
		one_of ~name:"struct_items" [
			"next_struct_item", struct_item >> skip (element Comma) >> struct_items;
			"end_of_struct_items", struct_item;
			"no_struct_item", epsilon]
	) and struct_item = lazy !! (
		one_of ~name:"struct_item" [
			"named_item", skip (element Period) >> any_identifier >> skip (element Assign) >> assignment;
			"ordered_item", assignment]
	) and message = lazy !! (
		one_of ~name:"message" [
			"", message_with_args;
			"no_arg", any_identifier]
	) and message_with_args = lazy !! (
		one_of ~name:"message" [
			"next_message", any_identifier >> skip (element Colon) >> expression_in_messaging >> message_with_args;
			"end_of_message", epsilon]
	) and assignment_operator = lazy !! (
		one_of_elements [
			Assign; Add_assign; Sub_assign; Mul_assign; Div_assign; Rem_assign;
			And_assign; Or_assign; Xor_assign;
			L_shift_assign; R_shift_assign]
	) and label = lazy !! (
		one_of ~name:"label" [
			"named_label", any_identifier >> skip (element Colon);
			"case", skip (element (R Reserved.CASE)) >> expression >> skip (element Colon);
			"default", skip (element (R Reserved.DEFAULT)) >> skip (element Colon)]
	) and for_cond = lazy !! (
		skip (element L_paren) >>
		expression_opt >>
		skip (element Semicolon) >>
		expression_opt >>
		skip (element Semicolon) >>
		expression_opt >>
		skip (element R_paren)
	) and closed_statement = lazy !! (
		one_of ~name:"statement" [
			"empty", skip (element Semicolon);
			"block", compound_statement;
			"local", declaration_specifiers >> init_declarator_list2 >> skip (element Semicolon);
			"statement_expression", statement_expression >> skip (element Semicolon);
			"goto", skip (element (R Reserved.GOTO)) >> any_identifier >> skip (element Semicolon);
			"break", skip (element (R Reserved.BREAK)) >> skip (element Semicolon);
			"return", skip (element (R Reserved.RETURN)) >> expression >> skip (element Semicolon);
			"asm", element (Asm "");
			"switch", skip (element (R Reserved.SWITCH)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				compound_statement;
			"do_while", skip (element (R Reserved.DO)) >> closed_statement >>
				skip (element (R Reserved.WHILE)) >> skip (element L_paren) >> expression >> skip (element R_paren) >> skip (element Semicolon);
			"label", label >> closed_statement;
			"while", skip (element (R Reserved.WHILE)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				closed_statement;
			"for", skip (element (R Reserved.FOR)) >> for_cond >>
				closed_statement;
			"if_else", skip (element (R Reserved.IF)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				closed_statement >> skip (element (R Reserved.ELSE)) >> closed_statement]
	) and open_statement = lazy !! (
		one_of ~name:"statement" [
			"label", label >> open_statement;
			"while", skip (element (R Reserved.WHILE)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				open_statement;
			"for", skip (element (R Reserved.FOR)) >> for_cond >>
				open_statement;
			"if", skip (element (R Reserved.IF)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				statement;
			"if_else", skip (element (R Reserved.IF)) >> skip (element L_paren) >> expression >> skip (element R_paren) >>
				closed_statement >> skip (element (R Reserved.ELSE)) >> open_statement]
	) and statement = lazy !! (
		one_of ~name:"statement" [
			"", open_statement;
			"", closed_statement]
	) and preorocessor_directive = lazy !! (
		element (Preprocessor_directive (Unknown ""))
	);;
	
end;;
